package com.sxr.webflux.util;

import com.sxr.integration.SecureFileRequest;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.MultiValueMap;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 响应式请求解析工具
 * 将ServerHttpRequest转换为业务请求对象
 *
 * @author SXR
 * @since 1.0.0
 */
public class ReactiveRequestParser {

    /**
     * 解析安全文件请求
     *
     * @param request 响应式HTTP请求
     * @param isPreview 是否为预览模式
     * @return 异步的安全文件请求对象
     */
    public Mono<SecureFileRequest> parseSecureFileRequest(ServerHttpRequest request, boolean isPreview) {
        return Mono.fromCallable(() -> {
            SecureFileRequest fileRequest = new SecureFileRequest();

            // 解析路径信息
            String pathInfo = extractPathInfo(request, isPreview);
            parseTenantAndFilePath(pathInfo, fileRequest);

            // 设置基本参数
            fileRequest.setPreview(isPreview);

            // 解析查询参数
            MultiValueMap<String, String> queryParams = request.getQueryParams();
            fileRequest.setSignature(getFirstParam(queryParams, "signature"));

            // 设置过期时间
            String expireParam = getFirstParam(queryParams, "expire");
            if (expireParam != null && !expireParam.trim().isEmpty()) {
                try {
                    fileRequest.setExpireTime(Long.parseLong(expireParam));
                } catch (NumberFormatException e) {
                    // 忽略无效的过期时间参数
                }
            }

            // 设置访问限制
            String limitParam = getFirstParam(queryParams, "limit");
            if (limitParam != null && !limitParam.trim().isEmpty()) {
                try {
                    fileRequest.setAccessLimit(Integer.parseInt(limitParam));
                } catch (NumberFormatException e) {
                    // 忽略无效的限制参数
                }
            }

            // 设置请求相关信息
            fileRequest.setClientIp(getClientIp(request));
            fileRequest.setUserAgent(getFirstHeader(request, "User-Agent"));
            fileRequest.setRangeHeader(getFirstHeader(request, "Range"));

            // 设置请求头
            fileRequest.setHeaders(extractHeaders(request));

            return fileRequest;
        });
    }

    /**
     * 解析JSON请求
     *
     * @param request 响应式HTTP请求
     * @return 异步的安全文件请求对象
     */
    public Mono<SecureFileRequest> parseJsonRequest(ServerHttpRequest request) {
        return request.getBody()
                .map(dataBuffer -> {
                    byte[] bytes = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(bytes);
                    return new String(bytes, StandardCharsets.UTF_8);
                })
                .reduce(new StringBuilder(), StringBuilder::append)
                .map(StringBuilder::toString)
                .map(this::parseJsonToSecureFileRequest)
                .switchIfEmpty(Mono.just(new SecureFileRequest()));
    }

    /**
     * 提取路径信息
     */
    private String extractPathInfo(ServerHttpRequest request, boolean isPreview) {
        String path = request.getPath().value();

        // 移除servlet路径前缀
        String prefix = isPreview ? "/sxr/preview/" : "/sxr/download/";
        if (path.startsWith(prefix)) {
            return path.substring(prefix.length());
        }

        return path;
    }

    /**
     * 解析租户ID和文件路径
     */
    private void parseTenantAndFilePath(String pathInfo, SecureFileRequest fileRequest) {
        if (pathInfo == null || pathInfo.trim().isEmpty()) {
            return;
        }

        // 移除开头的斜杠
        if (pathInfo.startsWith("/")) {
            pathInfo = pathInfo.substring(1);
        }

        // 简单的路径解析：/tenantId/filePath
        String[] parts = pathInfo.split("/", 2);
        if (parts.length >= 2) {
            fileRequest.setTenantId(parts[0]);
            fileRequest.setFilePath(parts[1]);
        } else if (parts.length == 1) {
            fileRequest.setFilePath(parts[0]);
        }

        // 设置文件名
        String filePath = fileRequest.getFilePath();
        if (filePath != null && !filePath.trim().isEmpty()) {
            int lastSlashIndex = filePath.lastIndexOf('/');
            if (lastSlashIndex >= 0 && lastSlashIndex < filePath.length() - 1) {
                fileRequest.setFileName(filePath.substring(lastSlashIndex + 1));
            } else {
                fileRequest.setFileName(filePath);
            }
        }
    }

    /**
     * 获取客户端IP
     */
    private String getClientIp(ServerHttpRequest request) {
        String ip = getFirstHeader(request, "X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = getFirstHeader(request, "Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = getFirstHeader(request, "WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = getFirstHeader(request, "HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = getFirstHeader(request, "HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddress() != null ?
                 request.getRemoteAddress().getAddress().getHostAddress() : null;
        }
        return ip;
    }

    /**
     * 提取请求头
     */
    private Map<String, String> extractHeaders(ServerHttpRequest request) {
        Map<String, String> headers = new HashMap<>();

        request.getHeaders().forEach((name, values) -> {
            if (values != null && !values.isEmpty()) {
                headers.put(name, values.get(0));
            }
        });

        return headers;
    }

    /**
     * 获取第一个查询参数值
     */
    private String getFirstParam(MultiValueMap<String, String> params, String name) {
        List<String> values = params.get(name);
        return (values != null && !values.isEmpty()) ? values.get(0) : null;
    }

    /**
     * 获取第一个请求头值
     */
    private String getFirstHeader(ServerHttpRequest request, String name) {
        List<String> values = request.getHeaders().get(name);
        return (values != null && !values.isEmpty()) ? values.get(0) : null;
    }

    /**
     * 简单的JSON解析（生产环境建议使用Jackson或Gson）
     */
    private SecureFileRequest parseJsonToSecureFileRequest(String json) {
        SecureFileRequest request = new SecureFileRequest();

        if (json == null || json.trim().isEmpty()) {
            return request;
        }

        // 移除花括号
        json = json.trim();
        if (json.startsWith("{")) {
            json = json.substring(1);
        }
        if (json.endsWith("}")) {
            json = json.substring(0, json.length() - 1);
        }

        // 简单解析键值对
        String[] pairs = json.split(",");
        for (String pair : pairs) {
            String[] keyValue = pair.split(":", 2);
            if (keyValue.length == 2) {
                String key = keyValue[0].trim().replaceAll("\"", "");
                String value = keyValue[1].trim().replaceAll("\"", "");

                switch (key) {
                    case "tenantId":
                        request.setTenantId(value);
                        break;
                    case "filePath":
                        request.setFilePath(value);
                        break;
                    case "fileName":
                        request.setFileName(value);
                        break;
                    case "preview":
                        request.setPreview(Boolean.parseBoolean(value));
                        break;
                    case "expireTime":
                        try {
                            request.setExpireTime(Long.parseLong(value));
                        } catch (NumberFormatException e) {
                            // 忽略无效值
                        }
                        break;
                    case "accessLimit":
                        try {
                            request.setAccessLimit(Integer.parseInt(value));
                        } catch (NumberFormatException e) {
                            // 忽略无效值
                        }
                        break;
                }
            }
        }

        return request;
    }
}
